﻿using Fdb.Model;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.IO;
using System.Reflection;
using System.Text;

namespace Fdb
{
    /// <summary>
    /// 数据库访问基类
    /// </summary>
    public abstract class DBHandler<T>
    {
        public string _TableName = string.Empty;
        public PropertyInfo _KeyProper = null;
        public DatabaseType _DatabaseType;
        public string connectionString;
        public DbTransaction _DbTransaction;//事务对象

        /// <summary>
        /// 构造方法
        /// </summary>
        public DBHandler(DatabaseType databaseType)
        {
            Type type = typeof(T);
            this._TableName = type.Name;
            this._KeyProper = Common.GetFirstDbKeyField<T>();
            this._DatabaseType = databaseType;
        }

        public DBHandler(DatabaseType databaseType, DbTransaction dbTransaction)
        {
            Type type = typeof(T);
            this._TableName = type.Name;
            this._KeyProper = Common.GetFirstDbKeyField<T>();
            this._DatabaseType = databaseType;
            this._DbTransaction = dbTransaction;
        }

        #region 获取数据库结构抽象方法

        /// <summary>
        /// 获取指定数据库下所有表信息
        /// </summary>
        /// <param name="dbname">数据库名称</param>
        /// <returns></returns>
        public abstract List<TableClass> GetDbTableList(string dbname);

        /// <summary>
        /// 获取指定数据库下指定表的所有字段信息
        /// </summary>
        /// <param name="dbname">数据库名称</param>
        /// <param name="tblname">表名称</param>
        /// <returns></returns>
        public abstract List<FieldClass> GetTblFieldList(string dbname, string tblname);

        #endregion 获取数据库结构抽象方法

        #region 基础抽象方法

        /// <summary>
        /// 测试数据库连接
        /// </summary>
        /// <returns></returns>
        public abstract ExecuteResult TestConnnection();

        /// <summary>
        /// 根据sql获得datatable
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public abstract DataTable GetDataTable(string sql);

        /// <summary>
        /// 根据sql和查询参数获得datatable
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="ht"></param>
        /// <returns></returns>
        public abstract DataTable GetDataTable(string sql, NHashtable ht);

        /// <summary>
        /// 执行SQL
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public abstract ExecuteResult ExecuteSQLWithResult(string sql);

        /// <summary>
        /// 执行sql
        /// </summary>
        /// <param name="conn"></param>
        /// <param name="sql"></param>
        /// <returns></returns>
        public abstract ExecuteResult ExecuteSQLWithConn(string conn, string sql);

        /// <summary>
        /// 执行参数化SQL
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="ht"></param>
        /// <returns></returns>
        public abstract ExecuteResult ExecuteSQLWithResult(string sql, NHashtable ht);

        /// <summary>
        /// 根据SQL获得数据值
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public abstract object GetDataObject(string sql);

        /// <summary>
        /// 根据SQL和查询参数获得数据值
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="ht"></param>
        /// <returns></returns>
        public abstract object GetDataObject(string sql, NHashtable ht);

        /// <summary>
        /// 获取分页记录
        /// </summary>
        /// <param name="pagedQuery"></param>
        /// <param name="pageIndex"></param>
        /// <returns></returns>
        public abstract DataTable GetDataTable(PagedQuery pagedQuery);

        /// <summary>
        /// 获取总页数
        /// </summary>
        /// <param name="pagedQuery"></param>
        /// <returns></returns>
        public abstract int GetCount(PagedQuery pagedQuery);

        #endregion 基础操作方法

        #region 增删改抽象方法

        /// <summary>
        /// 添加新记录
        /// </summary>
        /// <param name="tableName"></param>
        /// <param name="ht"></param>
        /// <returns></returns>
        public abstract ExecuteResult Insert(string tableName, NHashtable ht);

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public abstract ExecuteResult Insert(T t);

        /// <summary>
        /// 更新记录
        /// </summary>
        /// <param name="tableName"></param>
        /// <param name="ht"></param>
        /// <param name="where"></param>
        /// <returns></returns>
        public abstract ExecuteResult Update(string tableName, NHashtable ht, string where);

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public abstract ExecuteResult Update(T t);

        /// <summary>
        /// 根据编号删除
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public abstract ExecuteResult Delete(long id);

        /// <summary>
        /// 根据GUID删除
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public abstract ExecuteResult Delete(Guid guid);

        /// <summary>
        /// 删除指定对象
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public abstract ExecuteResult Delete(T t);

        #endregion 增删改抽象方法

        #region 泛型查询抽象方法

        /// <summary>
        /// 根据编号获取单个对象
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public abstract T Fetch(long id);

        /// <summary>
        /// 根据GUID获取单个对象
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public abstract T Fetch(Guid guid);

        /// <summary>
        /// 根据SQL获取单个对象
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public abstract T Fetch(string sql);

        /// <summary>
        /// 根据SQL和查询参数获取单个对象
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="ht"></param>
        /// <returns></returns>
        public abstract T Fetch(string sql, NHashtable ht);

        /// <summary>
        /// 根据实体对象获取匹配对象
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public abstract T Fetch(T t);

        /// <summary>
        /// 获取全部对象
        /// </summary>
        /// <returns></returns>
        public abstract List<T> FetchList();

        /// <summary>
        /// 根据SQL获取对象列表
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public abstract List<T> FetchList(string sql);

        /// <summary>
        /// 根据SQL和查询参数获取对象列表
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="ht"></param>
        /// <returns></returns>
        public abstract List<T> FetchList(string sql, NHashtable ht);

        /// <summary>
        /// 根据实体对象获取列表
        /// </summary>
        /// <returns></returns>
        public abstract List<T> FetchList(T t, string whereClause);

        /// <summary>
        /// 根据实体对象获取列表
        /// </summary>
        /// <returns></returns>
        public abstract List<T> FetchList(T t);

        /// <summary>
        /// 将DataRow数组转为List
        /// </summary>
        /// <param name="drs"></param>
        /// <returns></returns>
        public abstract List<T> FetchList(DataRow[] drs);

        /// <summary>
        /// 获取分页结果集
        /// </summary>
        /// <param name="t"></param>
        /// <param name="pagedQuery"></param>
        /// <returns></returns>
        public abstract List<T> FetchPageList(T t, PagedQuery pagedQuery);

        /// <summary>
        /// 获取记录总数
        /// </summary>
        /// <param name="t"></param>
        /// <param name="pagedQuery"></param>
        /// <returns></returns>
        public abstract int FetchCount(T t, PagedQuery pagedQuery);

        /// <summary>
        /// 获取记录总数
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public abstract int FetchCount(T t);

        #endregion 泛型查询抽象方法

        #region 参数构造方法

        /// <summary>
        ///  构建属性值哈希列表
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public virtual NHashtable CreateContentValues(T t)
        {
            NHashtable nhashtable = new NHashtable();
            PropertyInfo[] props = GetPropertyInfoArray();
            foreach (PropertyInfo proper in props)
            {
                if (this.IsOnlyReadField(proper.Name))
                {
                    continue;//或是只读属性则不进行增加修改
                }

                object o = proper.GetValue(t, null);
                string properType = proper.PropertyType.ToString().ToLower();

                if (o != null)
                {
                    if (properType.IndexOf("int") > -1)
                    {
                        int newValue = Convert.ToInt32(o);
                        if (newValue == int.MinValue)
                        {
                            o = null;
                        }
                    }

                    if (properType.IndexOf("double") > -1)
                    {
                        double newValue = Convert.ToDouble(o);
                        if (newValue == double.MinValue)
                        {
                            o = null;
                        }
                    }

                    if (properType.IndexOf("decimal") > -1)
                    {
                        decimal newValue = Convert.ToDecimal(o);
                        if (newValue == decimal.MinValue)
                        {
                            o = null;
                        }
                    }

                    if (properType.IndexOf("datetime") > -1)
                    {
                        DateTime newValue = Convert.ToDateTime(o);
                        if (newValue == DateTime.MinValue)
                        {
                            o = null;
                        }
                    }

                    nhashtable.Add(proper.Name, o);
                }
            }

            return nhashtable;
        }

        /// <summary>
        /// 根据实体对象构建查询条件
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public string BuildWhere(T t)
        {
            if (t == null)
            {
                return string.Empty;
            }

            string param_symbol = "@";
            if (this._DatabaseType == DatabaseType.Oracle)
            {
                param_symbol = ":";
            }

            string where = string.Empty;
            PropertyInfo[] props = GetPropertyInfoArray();

            string likeWhere = string.Empty;
            //foreach (PropertyInfo proper in props)
            //{
            //    object value = proper.GetValue(t, null);

            //    if (value != null)
            //    {
            //        string type = value.GetType().ToString();
            //        if (this.IsPrimaryKey(proper.Name))
            //        {
            //            if (type.IndexOf("System.String") == -1)
            //            {
            //                if (Convert.ToInt32(value.ToString()) == 0) //该属性为主键且值为0，不参与构造查询条件
            //                {
            //                    continue;
            //                }
            //            }
            //        }

            //        if (type.IndexOf("System.String") > -1)
            //        {
            //            if (!value.ToString().Equals("%%"))
            //            {
            //                if(value.ToString().IndexOf("%") > -1)
            //                {
            //                    if (!string.IsNullOrEmpty(likeWhere)) likeWhere += " or ";
            //                    likeWhere += proper.Name + " like " + param_symbol + proper.Name;
            //                }
            //            }
            //        }
            //    }
            //}

            //if (!string.IsNullOrEmpty(likeWhere))
            //{
            //    likeWhere = "(" + likeWhere + ")";
            //    where = likeWhere;
            //}

            foreach (PropertyInfo proper in props)
            {
                object value = proper.GetValue(t, null);

                if (value != null)
                {
                    string type = value.GetType().ToString();
                    if (this.IsPrimaryKey(proper.Name))
                    {
                        if (type.IndexOf("System.String") == -1)
                        {
                            if (Convert.ToInt32(value.ToString()) == 0) //该属性为主键且值为0，不参与构造查询条件
                            {
                                continue;
                            }
                        }
                    }

                    if (type.IndexOf("System.String") > -1)
                    {
                        if (!value.ToString().Equals("%%"))
                        {
                            string op = value.ToString().IndexOf("%") > -1 ? " like " : "=";
                            if (op.Trim().Equals("like"))
                            {
                                if (!string.IsNullOrEmpty(likeWhere)) likeWhere += " or  ";   //HACK：此处需要进一步整合
                                likeWhere += proper.Name + op + param_symbol + proper.Name;
                            }
                            else
                            {
                                if (!string.IsNullOrEmpty(where)) where += " and ";
                                where += proper.Name + op + param_symbol + proper.Name;
                            }

                            //if (value.ToString().IndexOf("%") == -1)
                            //{
                            //    if (!string.IsNullOrEmpty(where)) where += " and ";
                            //    where += proper.Name + " = " + param_symbol + proper.Name;
                            //}
                        }
                    }
                    else if (type.IndexOf("Int") > -1)
                    {
                        if (!value.ToString().Equals("-10000"))
                        {
                            if (!string.IsNullOrEmpty(where)) where += " and ";
                            where += proper.Name + "=" + param_symbol + proper.Name;
                        }
                    }
                    else if (type.IndexOf("Decimal") > -1)
                    {
                        if (!value.ToString().Equals("-10000"))
                        {
                            if (!string.IsNullOrEmpty(where)) where += " and ";
                            where += proper.Name + "=" + param_symbol + proper.Name;
                        }
                    }
                    //else if (type.IndexOf("System.DateTime") > -1) //此处是为了支持按日期匹配
                    //{
                    //    if (!string.IsNullOrEmpty(where)) where += " and ";
                    //    where += proper.Name + "=@" + proper.Name;
                    //}
                }
            }

            if (!string.IsNullOrEmpty(likeWhere))
            {
                likeWhere = "(" + likeWhere + ")";
            }

            if (!string.IsNullOrEmpty(where))
            {
                if (!string.IsNullOrEmpty(likeWhere)) where += " and ";
            }

            where += likeWhere;

            return where;
        }

        /// <summary>
        /// 根据实体构建参数列表
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public NHashtable BuildParams(T t)
        {
            if (t == null)
            {
                return null;
            }

            NHashtable paramtable = new NHashtable();
            PropertyInfo[] props = GetPropertyInfoArray();

            foreach (PropertyInfo proper in props)
            {
                object value = proper.GetValue(t, null);

                if (value != null)
                {
                    string type = value.GetType().ToString();
                    if (this.IsPrimaryKey(proper.Name))
                    {
                        if (type.IndexOf("System.String") == -1)
                        {
                            if (Convert.ToInt32(value.ToString()) == 0) //该属性为主键且值为0，不参与构造查询条件
                            {
                                continue;
                            }
                        }
                    }

                    if (type.IndexOf("System.String") > -1)
                    {
                        if (!value.ToString().Equals("%%"))
                        {
                            paramtable.Add(proper.Name, value);
                        }
                    }
                    else if (type.IndexOf("Int") > -1)
                    {
                        if (!value.ToString().Equals("-10000"))
                        {
                            paramtable.Add(proper.Name, value);
                        }
                    }
                    else if (type.IndexOf("Decimal") > -1)
                    {
                        if (!value.ToString().Equals("-10000"))
                        {
                            paramtable.Add(proper.Name, value);
                        }
                    }
                    //else if (type.IndexOf("System.DateTime") > -1) //此处是为了支持按日期匹配
                    //{
                    //    paramtable.Add(proper.Name, value);
                    //}
                }
            }

            return paramtable;
        }

        #endregion 参数构造方法

        #region 反射方法

        /// <summary>
        /// 获取类中属性数组
        /// </summary>
        /// <returns></returns>
        public PropertyInfo[] GetPropertyInfoArray()
        {
            PropertyInfo[] props = null;

            try
            {
                Type type = typeof(T);
                object obj = Activator.CreateInstance(type);
                props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            }
            catch (Exception ex)
            { }

            return props;
        }

        /// <summary>
        /// 获取对象中属性的值
        /// </summary>
        /// <param name="t"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        public object GetPropertyValue(T t, string propertyName)
        {
            Type type = typeof(T);
            PropertyInfo property = type.GetProperty(propertyName);
            if (property == null) return null;

            return property.GetValue(t, null);
        }

        /// <summary>
        /// 判断属性是否为数据表主键
        /// </summary>
        /// <param name="properName">属性名称</param>
        /// <returns></returns>
        public bool IsPrimaryKey(string properName)
        {
            var userKeyFields = Common.GetDbKeyFieldList<T>();
            foreach (PropertyInfo pinfo in userKeyFields)
            {
                if (pinfo.Name.Equals(properName))
                {
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// 判断是否为数据库只读属性
        /// </summary>
        /// <param name="properName"></param>
        /// <returns></returns>
        public bool IsOnlyReadField(string properName)
        {
            var userFields = Common.GetDbOnlyReadFieldList<T>();
            foreach (PropertyInfo pinfo in userFields)
            {
                if (pinfo.Name.Equals(properName))
                {
                    return true;
                }
            }

            return false;
        }

        #endregion 反射方法

        #region 数据库维护虚方法

        /// <summary>
        /// 创建数据库
        /// </summary>
        /// <param name="connectionString"></param>
        /// <param name="dbname"></param>
        public virtual ExecuteResult CreateDB(string connectionString, string dbname)
        {
            return null;
        }

        /// <summary>
        /// 判断数据表是否存在
        /// </summary>
        /// <param name="tableName"></param>
        /// <returns></returns>
        public virtual bool IsTableExist(string tableName)
        {
            return false;
        }

        /// <summary>
        /// 创建一个默认数据表
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <returns></returns>
        public virtual ExecuteResult CreateTable(string tableName)
        {
            return null;
        }

        /// <summary>
        /// 修改表名
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <returns></returns>
        public virtual ExecuteResult ModifyTable(string oldTableName, string newTableName)
        {
            return null;
        }

        /// <summary>
        /// 判断数据表是否存在
        /// </summary>
        /// <param name="field"></param>
        /// <returns></returns>
        public virtual bool IsFieldExist(FieldClass field)
        {
            return false;
        }

        /// <summary>
        /// 新增字段
        /// </summary>
        /// <param name="field">字段</param>
        /// <returns></returns>
        public virtual ExecuteResult CreateField(FieldClass field)
        {
            return null;
        }

        /// <summary>
        /// 删除字段
        /// </summary>
        /// <param name="field">field</param>
        /// <returns></returns>
        public virtual ExecuteResult DeleteField(FieldClass field)
        {
            return null;
        }

        /// <summary>
        /// 修改表名
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <returns></returns>
        public virtual ExecuteResult ModifyField(FieldClass oldField, FieldClass newField)
        {
            return null;
        }

        /// <summary>
        /// 根据实体类创建表
        /// </summary>
        /// <returns></returns>
        public virtual ExecuteResult CreateTable()
        {
            return null;
        }

        /// <summary>
        ///  创建业务流程视图
        /// </summary>
        /// <param name="bizViewName"></param>
        /// <param name="primary"></param>
        /// <param name="datasouceSQL"></param>
        /// <param name="flowCode"></param>
        /// <returns></returns>
        public virtual ExecuteResult CreateBizFlowView(string flowCode, string bizViewName, string primary, string datasouceSQL)
        {
            return null;
        }

        #endregion 数据库维护虚方法

        #region 基础成员方法

        /// <summary>
        /// 获取行号
        /// </summary>
        /// <returns></returns>
        public int GetRowNum(PagedQuery pagedQuery, object itemIndex)
        {
            int index = 0;
            int rowNum = 0;
            try
            {
                index = int.Parse(itemIndex.ToString());
            }
            catch
            {
                index = 0;
            }

            rowNum = index + (pagedQuery.PageIndex - 1) * pagedQuery.PageSize;
            return rowNum;
        }

        /// <summary>
        /// 添加指定数量的空行
        /// </summary>
        /// <param name="rows"></param>
        /// <returns></returns>
        public string AddEmptyRows(PagedQuery pagedQuery, int rows)
        {
            string html = string.Empty;
            for (int i = 0; i < pagedQuery.PageSize - pagedQuery.PageRecordCount; i++)
            {
                html += "<tr>";
                for (int j = 0; j < rows; j++)
                {
                    html += "<td>";
                    html += "&nbsp;";
                    html += "</td>";
                }
                html += "</tr>\n";
            }

            return html;
        }

        /// <summary>
        /// 初始化分页查询对象
        /// </summary>
        /// <param name="t"></param>
        /// <param name="pagedQuery"></param>
        public void InitPagedQuery(T t, PagedQuery pagedQuery)
        {
            pagedQuery.TMPWhereClause = pagedQuery.WhereClause;
            pagedQuery.TMPParamList.Clear();
            if (pagedQuery.ParamList != null)
            {
                foreach (string key in pagedQuery.ParamList.Keys)
                {
                    pagedQuery.TMPParamList.Add(key, pagedQuery.ParamList[key]);
                }
            }

            string whereClause = this.BuildWhere(t);
            NHashtable paramtable = this.BuildParams(t);
            pagedQuery.TableName = this._TableName;

            if (!string.IsNullOrEmpty(pagedQuery.TMPWhereClause))
            {
                if (!string.IsNullOrEmpty(whereClause))
                {
                    pagedQuery.TMPWhereClause += " and ";
                }
            }

            pagedQuery.TMPWhereClause = pagedQuery.TMPWhereClause + whereClause;

            if (paramtable != null)
            {
                foreach (string key in paramtable.Keys)
                {
                    pagedQuery.TMPParamList.Add(key, paramtable[key]);
                }
            }
        }

        #endregion 基础成员方法

        #region 存储过程及事务相关虚方法

        /// <summary>
        /// 执行带参数的存储过程
        /// </summary>
        /// <param name="storedProcName"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public virtual int RunProcedure(string storedProcName, IDataParameter[] parameters)
        {
            return -1;
        }

        /// <summary>
        /// 开启一个数据库事务对象
        /// </summary>
        /// <returns></returns>
        public virtual ExecuteResult BeginTransaction()
        {
            return null;
        }

        /// <summary>
        /// 根据存储过程获取DataTable对象
        /// </summary>
        /// <param name="storeProcName">存储过程名称</param>
        /// <returns></returns>
        public virtual DataTable GetDataTableWithStoreProc(string storeProcName)
        {
            return null;
        }

        /// <summary>
        /// 根据存储过程获取DataTable对象
        /// </summary>
        /// <param name="storeProcName">存储过程名称</param>
        /// <param name="ht">参数</param>
        /// <returns></returns>
        public virtual DataTable GetDataTableWithStoreProc(string storeProcName, NHashtable ht)
        {
            return null;
        }

        /// <summary>
        /// 执行事务
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="ht"></param>
        /// <returns></returns>
        public virtual ExecuteResult ExcuteTransactionSQL(string sql, NHashtable ht)
        {
            return null;
        }

        #endregion 存储过程及事务相关虚方法

        #region 基础增删改查虚方法

        /// <summary>
        /// 获得datarow
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public virtual DataRow GetDataRow(string sql)
        {
            DataTable dt = new DataTable();

            try
            {
                dt = this.GetDataTable(sql, null);
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return dt.Rows.Count == 0 ? null : dt.Rows[0];
        }

        /// <summary>
        /// 获得datarow
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="ht"></param>
        /// <returns></returns>
        public virtual DataRow GetDataRow(string sql, NHashtable ht)
        {
            DataTable dt = new DataTable();

            try
            {
                dt = this.GetDataTable(sql, ht);
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return dt.Rows.Count == 0 ? null : dt.Rows[0];
        }

        /// <summary>
        /// 根据对象的主键属性获取对象
        /// </summary>
        /// <param name="t">对象</param>
        /// <returns>对象</returns>
        public virtual T FetchByKey(T t)
        {
            Type type = typeof(T);
            PropertyInfo _keyProper = Common.GetFirstDbKeyField<T>();
            T instance = System.Activator.CreateInstance<T>();
            string keyProperType = _keyProper.PropertyType.ToString().ToLower();
            object keyProperValue = _keyProper.GetValue(t, null);
            if (keyProperType.IndexOf("int") > -1 || keyProperType.IndexOf("double") > -1
                 || keyProperType.IndexOf("decimal") > -1)
            {
                long keyval = Common.ConvertToLongWithOutNull(keyProperValue);
                instance = Fetch(keyval);
                if (instance != null)
                {
                    if (keyval == 0)
                    {
                        throw new Exception("表" + type.Name + "中主键字段" + _keyProper.Name + "存在0值的记录，WriteToDb方法不适用于新增。建议针对该表单独使用Insert或Update方法。");
                    }
                }
            }
            else
            {
                _keyProper.SetValue(instance, keyProperValue, null);
                instance = Fetch(instance);
            }

            return instance;
        }

        /// <summary>
        /// 数据行转为实例对象
        /// </summary>
        /// <param name="dr"></param>
        /// <returns></returns>
        public virtual T Fetch(DataRow dr)
        {
            if (dr == null) return default(T);
            else
            {
                T instance = System.Activator.CreateInstance<T>();
                PropertyInfo[] props = GetPropertyInfoArray();
                foreach (PropertyInfo proper in props)
                {
                    string propType = proper.PropertyType.ToString();
                    string properName = proper.Name;
                    object value = dr[properName];
                    if (value == System.DBNull.Value)
                    {
                        //XXX:此处会报类型“System.DBNull”的对象无法转换为类型“System.Nullable`1[System.Decimal]”。
                        //待优化。
                        if (propType.IndexOf("System.String") > -1)
                        {
                            proper.SetValue(instance, string.Empty, null);
                        }
                        else
                        {
                            proper.SetValue(instance, null, null);
                        }
                    }
                    else
                    {
                        if (propType.IndexOf("System.Int64") > -1)
                        {
                            proper.SetValue(instance, Convert.ToInt64(value.ToString()), null);
                        }
                        else
                        {
                            if (value.GetType().ToString().Equals("system.boolean"))
                            {
                                value = value.ToString().Equals("true") ? 1 : 0;
                                proper.SetValue(instance, value, null);
                            }
                            else if (value.GetType().ToString().ToLower().Equals("system.byte[]")) //默认为图片
                            {
                                if (proper.PropertyType.Name.ToLower().Equals("image"))
                                {
                                    Byte[] buff = new byte[0];
                                    buff = (Byte[])value;
                                    //MemoryStream ms = new MemoryStream(buff);
                                    //value = Image.FromStream(ms);
                                    //proper.SetValue(instance, value, null);
                                }
                            }
                            else if (propType.Equals("System.Nullable`1[System.Double]")) //此处判断 解决 类型“System.Decimal”的对象无法转换为类型“System.Nullable`1[System.Double]”。
                            {
                                if (string.IsNullOrEmpty(value.ToString()))
                                {
                                    value = null;
                                }
                                else
                                {
                                    value = Convert.ToDouble(value.ToString());
                                }

                                proper.SetValue(instance, value, null);
                            }
                            else if (propType.Equals("System.Nullable`1[System.Decimal]"))
                            {
                                if (string.IsNullOrEmpty(value.ToString()))
                                {
                                    value = null;
                                }
                                else
                                {
                                    value = Convert.ToDecimal(value.ToString());
                                }

                                proper.SetValue(instance, value, null);
                            }
                            else if (propType.IndexOf("System.Decimal") > -1)
                            {
                                proper.SetValue(instance, Convert.ToDecimal(value.ToString()), null);
                            }
                            else if (propType.IndexOf("System.Int32") > -1)
                            {
                                proper.SetValue(instance, Convert.ToInt32(value.ToString()), null);
                            }
                            else if (propType.IndexOf("System.DateTime") > -1)
                            {
                                proper.SetValue(instance, Convert.ToDateTime(value.ToString()), null);
                            }
                            else
                            {
                                proper.SetValue(instance, value, null);
                            }
                        }
                    }
                }

                return instance;
            }
        }

        /// <summary>
        /// 写入数据库
        /// </summary>
        /// <returns></returns>
        public virtual ExecuteResult WriteToDb(T t)
        {
            T instance = this.FetchByKey(t);//若主键等于0值，且表中有主键等于0的记录，则进行编辑
            if (instance == null)
            {
                return Insert(t);
            }

            PropertyInfo[] props = GetPropertyInfoArray();
            foreach (PropertyInfo proper in props)
            {
                object dbValueObj = proper.GetValue(instance, null);
                object newValueObj = proper.GetValue(t, null);
                string properType = proper.PropertyType.ToString().ToLower();

                //XXX：属性是null的话就不在更新该属性，如果确实需要更新为null怎么办？？
                //HACK；这里有问题，默认值为0的字段直接将原值覆盖了。 此处主要针对数字型，在类中给赋予？可空属性即可！
                //if (newValueObj != null)
                //{
                //    if (!newValueObj.Equals(dbValueObj))
                //    {
                //        dbValueObj = newValueObj;
                //    }

                //    if (properType.IndexOf("int") > -1)
                //    {
                //        int newValue = Convert.ToInt32(newValueObj);
                //        if (newValue == int.MinValue)
                //        {
                //            dbValueObj = null;
                //        }
                //    }

                //    if (properType.IndexOf("double") > -1)
                //    {
                //        double newValue = Convert.ToDouble(newValueObj);
                //        if (newValue == double.MinValue)
                //        {
                //            dbValueObj = null;
                //        }
                //    }

                //    if (properType.IndexOf("decimal") > -1)
                //    {
                //        decimal newValue = Convert.ToDecimal(newValueObj);
                //        if (newValue == decimal.MinValue)
                //        {
                //            dbValueObj = null;
                //        }
                //    }

                //    if (properType.IndexOf("datetime") > -1)
                //    {
                //        DateTime newValue = Convert.ToDateTime(newValueObj);
                //        if (newValue == DateTime.MinValue)
                //        {
                //            dbValueObj = null;
                //        }
                //    }
                //}

                proper.SetValue(instance, dbValueObj, null);

            }

            return Update(instance);
        }

        #endregion 基础增删改查虚方法
    }
}
